﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.SqlServer.Dts.Pipeline;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;

namespace MouldingAndMillwork.SSIS
{
    public partial class SSISUtility
    {
        #region CLASS: CustomProperty
        /// <summary>
        /// MetaData custom property utilities
        /// </summary>
        public class CustomProperty
        {
            #region Enumerations
            public enum CPEx
            {
                AllowExpressions,
                DenyExpressions
            }
            #endregion

            #region Creating
            #region Base Method - string
            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, string defaultValue, string description, 
                bool containsID, CPEx allowExpressions)
            {
                CustomProperty.Create(componentMetaData, propertyName, defaultValue, 
                    description, containsID, allowExpressions, null);
            }

            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, string defaultValue, string description, bool containsID, 
                CPEx allowExpressions, System.Type typeConverterClass)
            {
                try
                {
                    IDTSCustomProperty100 savedProperty = null;
                    foreach (IDTSCustomProperty100 possibleProperty in componentMetaData.CustomPropertyCollection)
                    {
                        if (possibleProperty.Name == propertyName)
                        {
                            savedProperty = possibleProperty;
                            break;
                        }
                    }
                    if (savedProperty == null)
                    {
                        savedProperty = componentMetaData.CustomPropertyCollection.New();
                        savedProperty.Name = propertyName;
                        savedProperty.Value = defaultValue;
                        savedProperty.ContainsID = containsID;
                    }
                    if (allowExpressions == CPEx.AllowExpressions)
                    {
                        savedProperty.ExpressionType = DTSCustomPropertyExpressionType.CPET_NOTIFY;
                    }
                    else
                    {
                        savedProperty.ExpressionType = DTSCustomPropertyExpressionType.CPET_NONE;
                    }
                    savedProperty.Description = description;
                    if (typeConverterClass != null)
                    {
                        savedProperty.TypeConverter = typeConverterClass.AssemblyQualifiedName;
                    }
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Base Method - long
            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, long defaultValue, string description, 
                bool containsID, CPEx allowExpressions)
            {
                CustomProperty.Create(componentMetaData, propertyName, defaultValue, 
                    description, containsID, allowExpressions, null);
            }

            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, long defaultValue, string description, 
                bool containsID, CPEx allowExpressions, System.Type typeConverterClass)
            {
                try
                {
                    IDTSCustomProperty100 savedProperty = null;
                    foreach (IDTSCustomProperty100 possibleProperty in componentMetaData.CustomPropertyCollection)
                    {
                        if (possibleProperty.Name == propertyName)
                        {
                            savedProperty = possibleProperty;
                            break;
                        }
                    }
                    if (savedProperty == null)
                    {
                        savedProperty = componentMetaData.CustomPropertyCollection.New();
                        savedProperty.Name = propertyName;
                        savedProperty.Value = defaultValue;
                        savedProperty.ContainsID = containsID;
                    }
                    if (allowExpressions == CPEx.AllowExpressions)
                    {
                        savedProperty.ExpressionType = DTSCustomPropertyExpressionType.CPET_NOTIFY;
                    }
                    else
                    {
                        savedProperty.ExpressionType = DTSCustomPropertyExpressionType.CPET_NONE;
                    }
                    savedProperty.Description = description;
                    if (typeConverterClass != null)
                    {
                        savedProperty.TypeConverter = typeConverterClass.AssemblyQualifiedName;
                    }
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Base Method - bool
            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, bool defaultValue, string description, 
                bool containsID, CPEx allowExpressions)
            {
                try
                {
                    IDTSCustomProperty100 savedProperty = null;
                    foreach (IDTSCustomProperty100 possibleProperty in componentMetaData.CustomPropertyCollection)
                    {
                        if (possibleProperty.Name == propertyName)
                        {
                            savedProperty = possibleProperty;
                            break;
                        }
                    }
                    if (savedProperty == null)
                    {
                        savedProperty = componentMetaData.CustomPropertyCollection.New();
                        savedProperty.Name = propertyName;
                        savedProperty.Value = defaultValue;
                        savedProperty.ContainsID = containsID;
                    }
                    if (allowExpressions == CPEx.AllowExpressions)
                    {
                        savedProperty.ExpressionType = DTSCustomPropertyExpressionType.CPET_NOTIFY;
                    }
                    else
                    {
                        savedProperty.ExpressionType = DTSCustomPropertyExpressionType.CPET_NONE;
                    }
                    savedProperty.Description = description;
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - int
            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, int defaultValue, string description, 
                bool containsID, CPEx allowExpressions)
            {
                try
                {
                    CustomProperty.Create(componentMetaData, propertyName, Convert.ToInt64(defaultValue), 
                        description, containsID, allowExpressions);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - decimal
            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, decimal defaultValue, string description, 
                bool containsID, CPEx allowExpressions)
            {
                try
                {
                    CustomProperty.Create(componentMetaData, propertyName, defaultValue.ToString(), 
                        description, containsID, allowExpressions);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - object (via XmlSerializer)
            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, object defaultValue, string description, 
                bool containsID, CPEx allowExpressions)
            {
                CustomProperty.Create(componentMetaData, propertyName, defaultValue, description, 
                    containsID, allowExpressions, null);
            }

            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, object defaultValue, string description, bool containsID, 
                CPEx allowExpressions, System.Type typeConverterClass)
            {
                try
                {
                    StringBuilder stringDefaultValue = new StringBuilder();
                    XmlSerializer serializer = new XmlSerializer(defaultValue.GetType());
                    XmlWriter xmlWriter = XmlWriter.Create(stringDefaultValue);
                    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                    ns.Add("", "");
                    serializer.Serialize(xmlWriter, defaultValue, ns);

                    CustomProperty.Create(componentMetaData, propertyName, stringDefaultValue.ToString(), 
                        description, containsID, allowExpressions, typeConverterClass);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - Size
            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, Size defaultValue, string description, 
                bool containsID, CPEx allowExpressions)
            {
                try
                {
                    string defaultValueStr = defaultValue.Width.ToString() + "," + defaultValue.Height.ToString();
                    CustomProperty.Create(componentMetaData, propertyName, defaultValueStr, 
                        description, containsID, allowExpressions);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - DateTime
            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, DateTime defaultValue, string description, 
                bool containsID, CPEx allowExpressions)
            {
                try
                {
                    CustomProperty.Create(componentMetaData, propertyName, (object)defaultValue, 
                        description, containsID, allowExpressions);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - DateTime?
            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, DateTime? defaultValue, string description, 
                bool containsID, CPEx allowExpressions)
            {
                try
                {
                    List<long> defaultValueList = new List<long>();
                    if (defaultValue.HasValue)
                    {
                        defaultValueList.Add(defaultValue.Value.ToBinary());
                    }
                    CustomProperty.Create(componentMetaData, propertyName, defaultValueList, 
                        description, containsID, allowExpressions);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - ValueType (enum)
            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, ValueType defaultValue, string description, 
                bool containsID, CPEx allowExpressions)
            {
                CustomProperty.Create(componentMetaData, propertyName, defaultValue, 
                    description, containsID, allowExpressions, null);
            }

            public static void Create(IDTSComponentMetaData100 componentMetaData,
                string propertyName, ValueType defaultValue, string description, 
                bool containsID, CPEx allowExpressions, System.Type typeConverterClass)
            {
                try
                {
                    CustomProperty.Create(componentMetaData, propertyName, Convert.ToInt32(defaultValue), 
                        description, containsID, allowExpressions, typeConverterClass);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion
            #endregion

            #region Loading
            #region Base Method - string
            public static string Load(IDTSComponentMetaData100 componentMetaData,
                string propertyName, string defaultValue, ref bool loadErrorOccurred)
            {
                try
                {
                    IDTSCustomProperty100 savedProperty = null;

                    foreach (IDTSCustomProperty100 prop in componentMetaData.CustomPropertyCollection)
                    {
                        if (prop.Name == propertyName)
                        {
                            savedProperty = prop;
                            break;
                        }
                    }
                    if (savedProperty == null)
                    {
                        loadErrorOccurred = true;
                        return defaultValue;
                    }
                    else
                    {
                        return Convert.ToString(savedProperty.Value);
                    }
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    throw;
                }
                #endregion
            }
            #endregion

            #region Base Method - long
            public static long Load(IDTSComponentMetaData100 componentMetaData,
                string propertyName, long defaultValue, ref bool loadErrorOccurred)
            {
                try
                {
                    IDTSCustomProperty100 savedProperty = null;

                    foreach (IDTSCustomProperty100 prop in componentMetaData.CustomPropertyCollection)
                    {
                        if (prop.Name == propertyName)
                        {
                            savedProperty = prop;
                            break;
                        }
                    }
                    if (savedProperty == null)
                    {
                        loadErrorOccurred = true;
                        return defaultValue;
                    }
                    else
                    {
                        return Convert.ToInt64(savedProperty.Value);
                    }
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    throw;
                }
                #endregion
            }
            #endregion

            #region Base Method - bool
            public static bool Load(IDTSComponentMetaData100 componentMetaData,
                string propertyName, bool defaultValue, ref bool loadErrorOccurred)
            {
                try
                {
                    IDTSCustomProperty100 savedProperty = null;

                    foreach (IDTSCustomProperty100 prop in componentMetaData.CustomPropertyCollection)
                    {
                        if (prop.Name == propertyName)
                        {
                            savedProperty = prop;
                            break;
                        }
                    }
                    if (savedProperty == null)
                    {
                        loadErrorOccurred = true;
                        return defaultValue;
                    }
                    else
                    {
                        return Convert.ToBoolean(savedProperty.Value);
                    }
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    throw;
                }
                #endregion
            }
            #endregion

            #region Extension Method - int
            public static int Load(IDTSComponentMetaData100 componentMetaData,
                string propertyName, int defaultValue, ref bool loadErrorOccurred)
            {
                try
                {
                    object actualValue = CustomProperty.Load(componentMetaData, propertyName, Convert.ToInt64(defaultValue), ref loadErrorOccurred);
                    return Convert.ToInt32(actualValue);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    throw;
                }
                #endregion
            }
            #endregion

            #region Extension Method - decimal
            public static decimal Load(IDTSComponentMetaData100 componentMetaData,
                string propertyName, decimal defaultValue, ref bool loadErrorOccurred)
            {
                try
                {
                    object actualValue = CustomProperty.Load(componentMetaData, propertyName, defaultValue.ToString(), ref loadErrorOccurred);
                    return Convert.ToDecimal(actualValue);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    throw;
                }
                #endregion
            }
            #endregion

            #region Extension Method - object (via XmlSerializer)
            public static object Load(IDTSComponentMetaData100 componentMetaData,
                string propertyName, object defaultValue, ref bool loadErrorOccurred)
            {
                try
                {
                    StringBuilder stringDefaultValue = new StringBuilder();
                    XmlSerializer serializer = new XmlSerializer(defaultValue.GetType());
                    XmlWriter xmlWriter = XmlWriter.Create(stringDefaultValue);
                    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                    ns.Add("", "");
                    serializer.Serialize(xmlWriter, defaultValue, ns);

                    string actualValue = CustomProperty.Load(componentMetaData, propertyName, stringDefaultValue.ToString(), ref loadErrorOccurred);

                    System.IO.StringReader stringReader = new System.IO.StringReader(actualValue);
                    return serializer.Deserialize(stringReader);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    throw;
                }
                #endregion
            }
            #endregion

            #region Extension Method - Size
            public static Size Load(IDTSComponentMetaData100 componentMetaData,
                string propertyName, Size defaultValue, ref bool loadErrorOccurred)
            {
                try
                {
                    string defaultValueStr = defaultValue.Width.ToString() + "," + defaultValue.Height.ToString();
                    string actualValueStr = CustomProperty.Load(componentMetaData, propertyName, defaultValueStr, ref loadErrorOccurred);
                    string[] tokens = actualValueStr.Split(',');
                    if (tokens.Length == 2)
                    {
                        return new Size(Convert.ToInt32(tokens[0]), Convert.ToInt32(tokens[1]));
                    }
                    else
                    {
                        return defaultValue;
                    }
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    throw;
                }
                #endregion
            }
            #endregion

            #region Extension Method - DateTime
            public static DateTime Load(IDTSComponentMetaData100 componentMetaData,
                string propertyName, DateTime defaultValue, ref bool loadErrorOccurred)
            {
                try
                {
                    object actualValue = CustomProperty.Load(componentMetaData, propertyName, defaultValue.ToBinary(), ref loadErrorOccurred);
                    return (DateTime)actualValue;
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    throw;
                }
                #endregion
            }
            #endregion

            #region Extension Method - DateTime?
            public static DateTime? Load(IDTSComponentMetaData100 componentMetaData,
                string propertyName, DateTime? defaultValue, ref bool loadErrorOccurred)
            {
                try
                {
                    List<long> defaultValueList = new List<long>();
                    if (defaultValue.HasValue)
                    {
                        defaultValueList.Add(defaultValue.Value.ToBinary());
                    }
                    List<long> actualValue = (List<long>)CustomProperty.Load(componentMetaData, propertyName, defaultValueList, ref loadErrorOccurred);
                    if (actualValue.Count == 0)
                    {
                        return null;
                    }
                    else
                    {
                        return DateTime.FromBinary(actualValue[0]);
                    }
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    throw;
                }
                #endregion
            }
            #endregion

            #region Extension Method - ValueType (enum)
            public static ValueType Load(IDTSComponentMetaData100 componentMetaData,
                string propertyName, ValueType defaultValue, ref bool loadErrorOccurred)
            {
                try
                {
                    object actualValue = CustomProperty.Load(componentMetaData, propertyName, Convert.ToInt32(defaultValue), ref loadErrorOccurred);
                    return (ValueType)actualValue;
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    throw;
                }
                #endregion
            }
            #endregion
            #endregion

            #region Saving
            #region Base Method - string
            public static void Save(IDTSComponentMetaData100 componentMetaData,
                string propertyName, string value)
            {
                try
                {
                    IDTSCustomProperty100 savedProperty = null;

                    foreach (IDTSCustomProperty100 prop in componentMetaData.CustomPropertyCollection)
                    {
                        if (prop.Name == propertyName)
                        {
                            savedProperty = prop;
                            break;
                        }
                    }
                    if (savedProperty == null)
                    {
                        savedProperty = componentMetaData.CustomPropertyCollection.New();
                    }

                    savedProperty.Name = propertyName;
                    savedProperty.Value = value;
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Base Method - long
            public static void Save(IDTSComponentMetaData100 componentMetaData,
                string propertyName, long value)
            {
                try
                {
                    IDTSCustomProperty100 savedProperty = null;

                    foreach (IDTSCustomProperty100 prop in componentMetaData.CustomPropertyCollection)
                    {
                        if (prop.Name == propertyName)
                        {
                            savedProperty = prop;
                            break;
                        }
                    }
                    if (savedProperty == null)
                    {
                        savedProperty = componentMetaData.CustomPropertyCollection.New();
                    }

                    savedProperty.Name = propertyName;
                    savedProperty.Value = value;
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Base Method - bool
            public static void Save(IDTSComponentMetaData100 componentMetaData,
                string propertyName, bool value)
            {
                try
                {
                    IDTSCustomProperty100 savedProperty = null;

                    foreach (IDTSCustomProperty100 prop in componentMetaData.CustomPropertyCollection)
                    {
                        if (prop.Name == propertyName)
                        {
                            savedProperty = prop;
                            break;
                        }
                    }
                    if (savedProperty == null)
                    {
                        savedProperty = componentMetaData.CustomPropertyCollection.New();
                    }

                    savedProperty.Name = propertyName;
                    savedProperty.Value = value;
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - int
            public static void Save(IDTSComponentMetaData100 componentMetaData,
                string propertyName, int value)
            {
                try
                {
                    CustomProperty.Save(componentMetaData, propertyName, Convert.ToInt64(value));
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - decimal
            public static void Save(IDTSComponentMetaData100 componentMetaData,
                string propertyName, decimal value)
            {
                try
                {
                    CustomProperty.Save(componentMetaData, propertyName, value.ToString());
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - Object (via XmlSerializer)
            public static void Save(IDTSComponentMetaData100 componentMetaData,
                string propertyName, object value)
            {
                try
                {
                    StringBuilder stringValue = new StringBuilder();
                    XmlSerializer serializer = new XmlSerializer(value.GetType());
                    XmlWriter xmlWriter = XmlWriter.Create(stringValue);
                    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                    ns.Add("", "");
                    serializer.Serialize(xmlWriter, value, ns);

                    CustomProperty.Save(componentMetaData, propertyName, stringValue.ToString());
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - Size
            public static void Save(IDTSComponentMetaData100 componentMetaData,
                string propertyName, Size value)
            {
                try
                {
                    string propertyStr = value.Width.ToString() + "," + value.Height.ToString();
                    CustomProperty.Save(componentMetaData, propertyName, propertyStr);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - DateTime
            public static void Save(IDTSComponentMetaData100 componentMetaData,
                string propertyName, DateTime value)
            {
                try
                {
                    CustomProperty.Save(componentMetaData, propertyName, (object)value);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - DateTime?
            public static void Save(IDTSComponentMetaData100 componentMetaData,
                string propertyName, DateTime? value)
            {
                try
                {
                    List<long> valueList = new List<long>();
                    if (value.HasValue)
                    {
                        valueList.Add(value.Value.ToBinary());
                    }
                    CustomProperty.Save(componentMetaData, propertyName, valueList);
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion

            #region Extension Method - ValueType (enum)
            public static void Save(IDTSComponentMetaData100 componentMetaData,
                string propertyName, ValueType value)
            {
                try
                {
                    CustomProperty.Save(componentMetaData, propertyName, Convert.ToInt32(value));
                }
                #region catch ...
                catch
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
                #endregion
            }
            #endregion
            #endregion

            #region Removing
            public static void Remove(IDTSComponentMetaData100 componentMetaData,
                string propertyName)
            {
                IDTSCustomProperty100 savedProperty = null;
                foreach (IDTSCustomProperty100 customProperty in componentMetaData.CustomPropertyCollection)
                {
                    if (customProperty.Name == propertyName)
                    {
                        savedProperty = customProperty;
                        break;
                    }
                }

                if (savedProperty != null)
                {
                    componentMetaData.CustomPropertyCollection.RemoveObjectByID(savedProperty.ID);
                }
            }
            #endregion

            #region Serializing
            #region string
            public static void SerializeProperty(XmlWriter writer, string propertyName, string value, string defaultValue)
            {
                if (value != defaultValue)
                {
                    writer.WriteAttributeString(propertyName, value);
                }
            }
            #endregion

            #region int
            public static void SerializeProperty(XmlWriter writer, string propertyName, int value, int defaultValue)
            {
                if (value != defaultValue)
                {
                    writer.WriteAttributeString(propertyName, Convert.ToString(value));
                }
            }
            #endregion

            #region bool
            public static void SerializeProperty(XmlWriter writer, string propertyName, bool value, bool defaultValue)
            {
                if (value != defaultValue)
                {
                    writer.WriteAttributeString(propertyName, Convert.ToString(value));
                }
            }
            #endregion
            #endregion

            #region Deserializing
            #region string
            public static string DeserializeProperty(XmlReader reader, string propertyName, string defaultValue)
            {
                if (reader[propertyName] == null)
                {
                    return defaultValue;
                }
                else
                {
                    return reader[propertyName];
                }
            }
            #endregion

            #region int
            public static int DeserializeProperty(XmlReader reader, string propertyName, int defaultValue)
            {
                if (reader[propertyName] == null)
                {
                    return defaultValue;
                }
                else
                {
                    return Convert.ToInt32(reader[propertyName]);
                }
            }
            #endregion

            #region bool
            public static bool DeserializeProperty(XmlReader reader, string propertyName, bool defaultValue)
            {
                if (reader[propertyName] == null)
                {
                    return defaultValue;
                }
                else
                {
                    return Convert.ToBoolean(reader[propertyName]);
                }
            }
            #endregion
            #endregion
        }
        #endregion

        #region CLASS: StringHashtable
        public class StringHashtable : IDictionary, IList, ICollection, IEnumerable
        {
            #region Private Constants
            private const string RESERVED_INTER = "|";
            private const string RESERVED_INTRA = "~";
            #endregion

            #region Private Variables
            protected List<string> _values;
            protected List<string> _keys;
            #endregion

            #region Constructor
            public StringHashtable()
            {
                this._keys = new List<string>();
                this._values = new List<string>();
            }
            #endregion

            #region Serialize and Deserialize
            public string Serialize()
            {
                string[] keys = new string[this._keys.Count];
                string[] values = new string[this._values.Count];
                int count = 0;

                for (int index = 0; index < this._keys.Count; index++)
                {
                    keys[index] = this._keys[index];
                    values[count] = this._values[index];
                    count++;
                }

                return string.Join(RESERVED_INTRA, keys) + RESERVED_INTER + string.Join(RESERVED_INTRA, values);
            }

            public static StringHashtable Deserialize(string serializedStringHashtable)
            {
                StringHashtable stringHashtable = new StringHashtable();

                if (serializedStringHashtable.Length > 0)
                {
                    string[] keysAndValues = serializedStringHashtable.Split('|');
                    string[] keys;
                    string[] values;
                    if (keysAndValues.Length == 2)
                    {
                        keys = keysAndValues[0].Split('~');
                        values = keysAndValues[1].Split('~');

                        for (int index = 0; index < keys.Length; index++)
                        {
                            stringHashtable.Add(keys[index], values[index]);
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Unable to deserialize '" + serializedStringHashtable + "' into a StringHashtable");
                    }
                }

                return stringHashtable;

            }
            #endregion

            #region IDictionary Members
            public void Add(string key, string value)
            {
                if (key.Contains(RESERVED_INTER) || key.Contains(RESERVED_INTRA))
                {
                    throw new ArgumentException("'" + RESERVED_INTER + "' and '" + RESERVED_INTRA + "' are not allowed in keys for StringHashtable");
                }
                else if (value.Contains(RESERVED_INTER) || value.Contains(RESERVED_INTRA))
                {
                    throw new ArgumentException("'" + RESERVED_INTER + "' and '" + RESERVED_INTRA + "' are not allowed in values for StringHashtable");
                }
                this._keys.Add(key);
                this._values.Add(value);
            }

            public void Add(object key, object value)
            {
                if (key.GetType() != typeof(string))
                {
                    throw new ArgumentException("Key must be a string.");
                }
                if (value.GetType() != typeof(string))
                {
                    throw new ArgumentException("Value must be a string.");
                }
                this.Add((string)key, (string)value);
            }

            public void Clear()
            {
                this._keys.Clear();
                this._values.Clear();
            }

            public bool Contains(string key)
            {
                return this._keys.Contains(key);
            }

            public bool Contains(object key)
            {
                if (key.GetType() != typeof(string))
                {
                    throw new ArgumentException("Key must be a string.");
                }
                return this.Contains((string)key);
            }

            public IDictionaryEnumerator GetEnumerator()
            {
                return new StringHashtableEnumerator(this);
            }

            public bool IsFixedSize
            {
                get { return false; }
            }

            public bool IsReadOnly
            {
                get { return false; }
            }

            public ICollection Keys
            {
                get { return this._keys; }
            }

            public void Remove(string key)
            {
                int index = this._keys.IndexOf(key);
                if (index >= 0)
                {
                    this._keys.RemoveAt(index);
                    this._values.RemoveAt(index);
                }
            }

            public void Remove(object key)
            {
                if (key.GetType() != typeof(string))
                {
                    throw new ArgumentException("Key must be a string.");
                }
                this.Remove((string)key);
            }

            public ICollection Values
            {
                get { return this._values; }
            }

            public string this[string key]
            {
                get
                {
                    int index = this._keys.IndexOf(key);
                    if (index >= 0)
                    {
                        return this._values[index];
                    }
                    else
                    {
                        return null;
                    }
                }
                set
                {
                    if (key.Contains(RESERVED_INTER) || key.Contains(RESERVED_INTRA))
                    {
                        throw new ArgumentException("'" + RESERVED_INTER + "' and '" + RESERVED_INTRA + "' are not allowed in keys for StringHashtable");
                    }
                    else if (value.Contains(RESERVED_INTER) || value.Contains(RESERVED_INTRA))
                    {
                        throw new ArgumentException("'" + RESERVED_INTER + "' and '" + RESERVED_INTRA + "' are not allowed in values for StringHashtable");
                    }
                    int index = this._keys.IndexOf(key);
                    if (index >= 0)
                    {
                        this._values[index] = value;
                    }
                    else
                    {
                        this._keys.Add(key);
                        this._values.Add(value);
                    }
                }
            }

            public string this[int index]
            {
                get { return this._values[index]; }
                set { this._values[index] = value; }
            }

            public object this[object key]
            {
                get
                {
                    if (key.GetType() != typeof(string))
                    {
                        throw new ArgumentException("Key must be a string.");
                    }
                    return this[(string)key];
                }
                set
                {
                    if (key.GetType() != typeof(string))
                    {
                        throw new ArgumentException("Key must be a string.");
                    }
                    if (value.GetType() != typeof(string))
                    {
                        throw new ArgumentException("Value must be a string.");
                    }
                    this[(string)key] = (string)value;
                }
            }
            #endregion

            #region ICollection Members
            public void CopyTo(Array array, int index)
            {
                for (int myIndex = 0; myIndex < this._values.Count; myIndex++)
                {
                    array.SetValue(this._values[myIndex], index + myIndex);
                }
            }

            public int Count
            {
                get { return this._keys.Count; }
            }

            public bool IsSynchronized
            {
                get { return false; }
            }

            public object SyncRoot
            {
                get { return null; }
            }
            #endregion

            #region IEnumerable Members
            IEnumerator IEnumerable.GetEnumerator()
            {
                return this._keys.GetEnumerator();
            }
            #endregion

            #region IList Members
            public int Add(object value)
            {
                if (value.GetType() != typeof(string))
                {
                    throw new ArgumentException("Value must be a string.");
                }
                this.Add((string)value, (string)value);
                return this._values.Count - 1;
            }

            public int IndexOf(object value)
            {
                if (value.GetType() != typeof(string))
                {
                    throw new ArgumentException("Value must be a string.");
                }
                return this._values.IndexOf((string)value);
            }

            public void Insert(int index, object value)
            {
                if (value.GetType() != typeof(string))
                {
                    throw new ArgumentException("Value must be a string.");
                }
                this._keys.Insert(index, (string)value);
                this._values.Insert(index, (string)value);
            }

            public void RemoveAt(int index)
            {
                this._keys.RemoveAt(index);
                this._values.RemoveAt(index);
            }

            object IList.this[int index]
            {
                get { return this[index]; }
                set
                {
                    if (value.GetType() != typeof(string))
                    {
                        throw new ArgumentException("Value must be a string.");
                    }
                    if (this._keys[index] == this._values[index])
                    {
                        this._keys[index] = (string)value;
                    }
                    this._values[index] = (string)value;
                }
            }

            #endregion

            #region CLASS: StringHashtableEnumerator
            public class StringHashtableEnumerator : IDictionaryEnumerator
            {
                private int _current;
                private StringHashtable _items;

                public StringHashtableEnumerator(StringHashtable items)
                {
                    this._current = -1;
                    this._items = items;
                }

                #region IDictionaryEnumerator Members

                public DictionaryEntry Entry
                {
                    get
                    {
                        if ((this._current < 0) || (this._current >= this._items.Count))
                        {
                            throw new InvalidOperationException();
                        }
                        return new DictionaryEntry(this._items._keys[this._current], this._items._values[this._current]);
                    }
                }

                public object Key
                {
                    get
                    {
                        if ((this._current < 0) || (this._current >= this._items.Count))
                        {
                            throw new InvalidOperationException();
                        }
                        return this._items._keys[this._current];
                    }
                }

                public object Value
                {
                    get
                    {
                        if ((this._current < 0) || (this._current >= this._items.Count))
                        {
                            throw new InvalidOperationException();
                        }
                        return this._items[this._current];
                    }
                }

                #endregion

                #region IEnumerator Members

                public object Current
                {
                    get
                    {
                        if ((this._current < 0) || (this._current >= this._items.Count))
                        {
                            throw new InvalidOperationException();
                        }
                        return this._items[this._current];
                    }
                }

                public bool MoveNext()
                {
                    this._current++;
                    return (this._current < this._items.Count);
                }

                public void Reset()
                {
                    this._current = -1;
                }

                #endregion
            }
            #endregion
        }
        #endregion


    }
}
